Attribute directive 可以改變 element 本身的行為、也可以為 element 擴展新的能力。但有時候我們可能會需要在 component 內直接與 directive 的實體互動,藉以達成更多效果。
在 Angular 內要取得 directive 的方法,就是透過 @Directive decorator 內的 exportAs
這個屬性,來讓 Angular 可以在 template variable 辨識出這個變數指向的是 directive 而非 element 本身。
// HTML
<p>app works!</p>
<button (click)="clickMe()">Click me to add new item!</button>
<ol appMydir #tMydir='mydir'>
</ol>
// TypeScript
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
@ViewChild('tMydir') mydir: MydirDirective;
title = 'day12';
clickMe(): void {
this.mydir.add();
}
}
↑ Block 1:AppComponent
@Directive({
selector: '[appMydir]',
exportAs: 'mydir'
})
export class MydirDirective implements OnChanges {
count = 1;
constructor(private ele: ElementRef<HTMLDivElement>) {}
add(): void {
const litem = document.createElement('li');
litem.textContent = `item ${++this.count}`;
this.ele.nativeElement.appendChild(litem);
}
}
↑ Block 2:MydirDirective
範例的程式碼很單純,我在 MydirDirective 的 @Directive decorator 新增了一個 exportAs 屬性,並在 AppComponent 的 ol element 使用這個 directive,同時新增一個 template variable:#tMydir
,並指派 mydir
。最後就可以在 AppComponent 內透過 @ViewChild('tMydir')
的方式來取得 MydirDirective 的實體,並使用這個 directive 的方法來新增 li element。
↑ Image 1:範例結果
以上就是今天要介紹的 Tip!只要在 @Directive 加入 exportAs 的屬性,就可以搭配 template variables 以及 @ViewChild 的方式來取得 directive 的實體囉!
以下是針對 Angular 怎麼處理 template variables 的過程,有興趣的讀者歡迎繼續閱讀!
const _c0 = ["tMydir"];
class AppComponent {
// ... 略
}
AppComponent.ɵcmp = _angular_core__WEBPACK_IMPORTED_MODULE_0__[
"ɵɵdefineComponent"
]({
type: AppComponent,
selectors: [["app-root"]],
viewQuery: function AppComponent_Query(rf, ctx) {
// ... 略
},
decls: 6,
vars: 0,
consts: [
[3, "click"],
["appMydir", ""],
["tMydir", "mydir"],
],
template: function AppComponent_Template(rf, ctx) {
if (rf & 1) {
// ... 略
_angular_core__WEBPACK_IMPORTED_MODULE_0__["ɵɵelement"](4, "ol", 1, 2);
}
},
directives: [_mydir_directive__WEBPACK_IMPORTED_MODULE_1__["MydirDirective"]],
styles: [
// ... 略
],
});
↑ Block 3:AppComponent 經過 compile 的結果
ɵɵelement
函式的傳入參數,分別是 index、name、attrsIndex 以及今天能夠處理 template variable 的關鍵:localRefsIndex
。
以本例來說,ol 這個 element 身上帶著 appMydir 這個 attribute directive 所以它的 attrsIndex 會是:1,同時它也身上帶著 #tMydir 這個 template variable,所以它的 localRefsIndex 是:2。
當 Angular 在 render 這個 component 的時候,就會按照以下的順序來處理 template variables:
最終就是由 resolveDirectives 來處理與 directive 有關的事情了。
至於 Angular 怎麼透過 @ViewChild 來找出 template variable 所對應的 element 或是 directive 的實體,就又是另一篇文章了。
以下按照入團順序列出我們團隊夥伴的系列文章!